package com.qiqidream.admin.security.url;

import com.google.common.collect.Sets;
import com.qiqidream.admin.common.config.IgnoresCustomConfig;
import com.qiqidream.admin.common.constant.StaticConstants;
import com.qiqidream.admin.system.service.MenuService;
import com.qiqidream.admin.system.service.RoleService;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;


/**
 * 获取访问该url所需要的用户角色权限信息
 * @author QiQiDream
 * @since 2019/11/18 9:52
 */
@Component
public class UrlFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Resource
    MenuService menuService;
    @Resource
    RoleService roleService;
    @Resource
    private IgnoresCustomConfig ignoresCustomConfig;

    /***
     * 返回该url所需要的用户权限信息(null：标识不需要任何权限都可以访问)
     * @param object: 储存请求url信息
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {

        HttpServletRequest request = ((FilterInvocation) object).getRequest();
        // 获取当前请求url,替换其中的id为**（本程序中id为19位数字）
        String requestUrl = "\"" + request.getServletPath().replaceAll("(^|[^\\d])(\\d{19})", "$1**") + "\"";
        String method = request.getMethod().toLowerCase();

        // 忽略url 放在此处进行过滤放行
        if (ignoresCustomConfig.checkIgnores(request)) {
            return null;
        }

        // 获取该url的详细信息
        List<Long> menuId = menuService.getCodeByUrl(requestUrl,method);

        List<String> roleCodes = new ArrayList<>();
        for (Long id : menuId){
            // 获取拥有该菜单的所有角色
            List<String> codes = roleService.getRolesByMenuId(id);
            roleCodes.addAll(codes);
        }

        // 如果没有角色拥有资源则为非法访问，返回非法角色(权限控制严格), 否则返回对应角色信息
//        return ObjectUtils.isEmpty(roleCodes)?SecurityConfig.createList(StaticConstants.ROLE_UNAUTHORIZED):SecurityConfig.createList(roleCodes.stream().distinct().toArray(String[]::new));

        // 如果没有角色拥有资源，则直接放行(权限控制较松), 否则返回对应角色信息
        return SecurityConfig.createList(roleCodes.stream().distinct().toArray(String[]::new));
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return FilterInvocation.class.isAssignableFrom(aClass);
    }

}
